package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * 定义了IOC容器的基本功能
 */
public interface BeanFactory {

    /**
     * 用来区分通过容器来获取FactoryBean产生的对象和获取FactoryBean本身
     */
    String FACTORY_BEAN_PREFIX = "&";


    /**
     * 根据name返回一个可以共享或独立的实例
     */
    Object getBean(String name) throws BeansException;

    /**
     * 根据name和requiredType返回一个可以共享或独立的实例
     */
    <T> T getBean(String name, @Nullable Class<T> requiredType) throws BeansException;

    /**
     * 返回一个可以共享或独立的实例
     * 允许指定显式构造函数参数/工厂方法参数，覆盖bean定义中指定的默认参数（如果有）
     */
    Object getBean(String name, Object... args) throws BeansException;

    /**
     * 返回唯一匹配给定对象类型的bean实例（如果有）。
     */
    <T> T getBean(Class<T> requiredType) throws BeansException;

    /**
     * 返回指定bean的实例，该实例可以是共享的或独立的。
     * 允许指定显式构造函数参数/工厂方法参数，覆盖bean定义中指定的默认参数（如果有）。
     */
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;


    /**
     * 此BeanFactory是否包含具有给定名称的bean定义或外部注册的singleton实例？
     * 如果BeanFactory是分层的，则会询问任何父BeanFactory是否在此BeanFactory实例中找不到bean。
     * 如果找到与给定名称匹配的bean定义或单例实例，此方法将返回{@code true}，
     * 无论命名bean定义是具体还是抽象，lazy或eager，是否在作用域内。
     * 因此，请注意此方法的{@code true} *返回值不一定表示{@link #getBean} 将能够获取同名的实例。
     */
    boolean containsBean(String name);

    /**
     * 是否为单例模式
     */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    /**
     * 是否为原型模式，每次通过容器的getBean方法获取对象时都将产生一个新的Bean实例
     */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    /**
     * 检查具有给定名称的bean是否与指定的类型匹配
     */
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 给定name的bean是否与指定的类型匹配.
     */
    boolean isTypeMatch(String name, @Nullable Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 返回给的name的bean的类型
     */
    @Nullable
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    /**
     * 返回给定name的bean的别名
     */
    String[] getAliases(String name);

}
